package com.qdxht.dispenser.service;

import android.content.Context;
import android.text.TextUtils;

import com.qdxht.dispenser.BuildConfig;
import com.qdxht.dispenser.utils.BroadcastUtil;
import com.qdxht.dispenser.utils.ConfigUtil;
import com.qdxht.dispenser.utils.DeviceIdUtil;
import com.qdxht.dispenser.utils.MqttUtil;
import com.qdxht.dispenser.utils.MqttUtil.OnMessageArrivedListener;
import com.qdxht.dispenser.utils.SpUtils;
import com.qdxht.dispenser.utils.update.VersionUpdateUtil;

import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
import timber.log.Timber;

import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 桥接MQTT与串口服务，实现命令流转
 */
public class MqttSerialBridge {

    private static final String TAG = "MqttSerialBridge";

    private final Context context;
    private final SerialPortService serialPortService;
    private final String mainboardCode;

    public MqttSerialBridge(Context context, SerialPortService serialPortService) {
        this.context = context;
        this.serialPortService = serialPortService;
        this.mainboardCode = DeviceIdUtil.getAndroidId(context);
    }

    public void start() {
        String topic = "device/" + mainboardCode + "/download/control";
        // 订阅控制主题
        MqttUtil.subscribe(topic, 2, MqttUtil.createMessageListener(new OnMessageArrivedListener() {
            @Override
            public void onMessageArrived(String topic, String payload, MqttMessage message) {
                handleMqttCommand(payload);
            }
        }));
        
        // 启动时清理过期的消息记录
        cleanExpiredMessageRecords();
    }

    private void handleMqttCommand(String payload) {
        Timber.tag(TAG).i( "收到MQTT消息：" + payload);
        try {
            JSONObject json = new JSONObject(payload);
            String operation = json.optString("operation");
            JSONObject content = json.optJSONObject("content");
            if (TextUtils.isEmpty(operation) || content == null) return;
            String uuid = content.optString("uuid");

            // 重复消息处理逻辑：1小时内相同operation和uuid的消息不处理
            String messageKey = operation + "_" + uuid;
            long currentTime = System.currentTimeMillis();
            long lastProcessTime = SpUtils.decodeLong("mqtt_msg_" + messageKey);
            
            // 如果1小时内处理过相同消息，则跳过
            if (lastProcessTime > 0 && (currentTime - lastProcessTime) < 3600000) { // 3600000ms = 1小时
                Timber.tag(TAG).i("重复消息，跳过处理：" + messageKey);
                return;
            }
            
            // 记录当前消息处理时间
            SpUtils.encode("mqtt_msg_" + messageKey, currentTime);
            
            // 维护消息key集合，用于后续清理
            Set<String> allKeys = SpUtils.decodeStringSet("mqtt_msg_keys");
            // 创建一个新的HashSet来存储所有的key，避免UnsupportedOperationException
            Set<String> newKeys = new HashSet<>();
            if (allKeys != null) {
                newKeys.addAll(allKeys);
            }
            newKeys.add(messageKey);
            SpUtils.encodeSet("mqtt_msg_keys", newKeys);

            // 如果设备停用，不处理启用以外的消息
            if(!ConfigUtil.getEnableDevice() && !"enable".equals(operation)){
                Timber.tag(TAG).i( "设备已停用，不处理操作：" + operation);
                sendMqttResponse(operation, uuid,  "failed", "设备已停用");
                return;
            }
            switch (operation) {
                case "bagComesOut": {
                    // 1、出袋
                    serialPortService.sendDispenseWithResult((success, msg, result) -> {
                        // 上报出袋消息
                        sendMqttResponse(operation, uuid, success ? "success" : "failed", msg);
                        if(success){
                            // 出袋成功，扣库存，上报库存信息
                            ConfigUtil.setInventory(ConfigUtil.getInventory() - 1);
                            sendMqttInventory();
                            // 判断是否预警
                            if(ConfigUtil.getInventoryAlarmThreshold() >= ConfigUtil.getInventory()){
                                sendMqttInventoryAlarm();
                            }
                            // 刷新界面库存
                            BroadcastUtil.sendInventoryBroadcast(context);
                            Timber.tag(TAG).i( "出袋成功：出袋后库存" + ConfigUtil.getInventory());
                        }
                    });
                    return;
                }
                case "disable":{
                    // 2、停用设备
                    ConfigUtil.setEnableDevice(false);
                    String url = content.optString("url");
                    ConfigUtil.setEnableImage(url);
                    BroadcastUtil.sendEnableDeviceBroadcast(context);
                    break;
                }
                case "enable":
                    // 3、启用设备
                    ConfigUtil.setEnableDevice(true);
                    BroadcastUtil.sendEnableDeviceBroadcast(context);
                    break;
                case "timerSwitch":{
                    // 4、定时开关
                    boolean timerSwitch = content.optBoolean("timerSwitch", true);
                    //开机时间："06:00:00"
                    String enableTime = content.optString("enableTime");
                    //关机时间："23:00:00"
                    String disableTime = content.optString("disableTime");
                    ConfigUtil.setTimerSwitch(timerSwitch);
                    ConfigUtil.setEnableTime(enableTime);
                    ConfigUtil.setDisableTime(disableTime);
                    BroadcastUtil.sendTimerSwitchBroadcast(context);
                    break;
                }
                case "setAd":
                    // 5、设置广告信息
                    BroadcastUtil.sendSetAdBroadcast(context, content.toString());
                    break;
                case "setQRCode":{
                    // 6、设置二维码
                    String QRCode = content.optString("QRCode");
                    ConfigUtil.setQRCode(QRCode);
                    BroadcastUtil.sendQRCodeBroadcast(context);
                    break;
                }
                case "setInventoryAlarmThreshold":{
                    // 7、设置库存报警阈值
                    int number = content.optInt("inventoryAlarmThreshold",10);
                    ConfigUtil.setInventoryAlarmThreshold(number);
                    break;
                }
                case "setGPSAlarmThreshold":{
                    // 8、设置定位偏差阈值
                    int number = content.optInt("gpsAlarmThreshold",50);
                    ConfigUtil.setGPSAlarmThreshold(number);
                    break;
                }
                case "setInventory":{
                    // 9、设置库存
                    int number = content.optInt("inventory",10);
                    String hexConfigValue = Integer.toHexString(number);
                    if (hexConfigValue.length() % 2 != 0) {
                        hexConfigValue = "0" + hexConfigValue;
                    }
                    serialPortService.sendWriteConfigWithResult(05,hexConfigValue, (success, msg, result) -> {
                        // 上报消息
                        sendMqttResponse(operation, uuid, success ? "success" : "failed", msg);
                        if(success){
                            ConfigUtil.setInventory(number);
                            BroadcastUtil.sendInventoryBroadcast(context);
                        }
                        Timber.tag(TAG).i( "设置库存：" + success + " " + msg);
                    });
                    return;
                }
                case "updateApp":{
                    // 10、版本更新
                    String version = content.optString("version");
                    if(!VersionUpdateUtil.isNewVersion(context, version)){
                        String url = content.optString("url");
                        BroadcastUtil.sendDownloadUpdateBroadcast(context, url);
                    }
                    break;
                }
                default:
                    return;
            }
            // 组装响应并上报（非bagComesOut等立即响应的命令）
            sendMqttResponse(operation, uuid,  "success", "操作成功");
        } catch (Exception e) {
            Timber.tag(TAG).e( "handleMqttCommand异常:%s", e.getMessage());
        }
    }

    public void sendMqttResponse(String operation, String uuid, String result, String msg) {
        try {
            JSONObject resp = new JSONObject();
            resp.put("operation", operation);
            resp.put("uuid", uuid);
            resp.put("mainboardCode", mainboardCode);
            resp.put("result", result);
            resp.put("msg", msg);
            MqttUtil.publish(MqttManagerService.TOPIC_RESPONSE, resp.toString(), 2, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上报库存信息：每次出袋时上报
     */
    public void sendMqttInventory() {
        try {
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            resp.put("inventory", ConfigUtil.getInventory());
            MqttUtil.publish(MqttManagerService.TOPIC_INVENTORY, resp.toString(), 1, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 库存低于阈值时报警
     */
    public void sendMqttInventoryAlarm() {
        try {
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            resp.put("inventory", ConfigUtil.getInventory());
            MqttUtil.publish(MqttManagerService.TOPIC_INVENTORYALARM, resp.toString(), 1, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 位置信息上报：30分钟一次
     */
    public void sendMqttGpsInfo(double lon,double lat,String addr) {
        try {
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            resp.put("lon", lon);
            resp.put("lat", lat);
            resp.put("addr", addr);
            MqttUtil.publish(MqttManagerService.TOPIC_GPSINFO, resp.toString(), 0, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 移动范围超过定位偏差阈值时报警：
     * APP每10分钟获取一次定位数据，并与上一次获取的定位数据做对比
     */
    public void sendMqttGpsAlarm(double lon,double lat,String addr) {
        try {
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            resp.put("lon", lon);
            resp.put("lat", lat);
            resp.put("addr", addr);
            MqttUtil.publish(MqttManagerService.TOPIC_GPSALARM, resp.toString(), 1, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 发送MQTT消息
     * @param topic 主题
     * @param payload 负载
     * @param qos 服务质量
     */
    public void sendMqttMessage(String topic, String payload, int qos) {
        MqttUtil.publish(topic, payload, qos, false);
    }

    /**
     * 上报设备状态
     */
    public void sendMqttStatus(int status,int signalIntensity) {
        try {
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            resp.put("status", status);
            resp.put("signalIntensity", signalIntensity);
            MqttUtil.publish(MqttManagerService.TOPIC_STATUS, resp.toString(), 1, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public void getDeviceState(int signalIntensity) {
        serialPortService.sendReadSensorWithResult(05, (success, msg, result) -> {
            // 上报消息
            sendMqttStatus(success ? Integer.parseInt(result.getData(), 16) : 5,signalIntensity);
        });
    }

    /**
     * 清理过期的消息记录（超过1小时的消息记录）
     */
    private void cleanExpiredMessageRecords() {
        try {
            long currentTime = System.currentTimeMillis();
            long expireTime = currentTime - 3600000; // 1小时前的时间戳
            
            // 获取所有以"mqtt_msg_"开头的key
            Set<String> allKeys = SpUtils.decodeStringSet("mqtt_msg_keys");
            if (allKeys == null) {
                return; // 没有需要清理的键
            }
            
            // 创建一个新的集合来存储保留的键
            Set<String> keysToKeep = new HashSet<>();
            
            for (String key : allKeys) {
                long messageTime = SpUtils.decodeLong("mqtt_msg_" + key);
                if (messageTime > 0 && messageTime < expireTime) {
                    // 删除过期的消息记录
                    SpUtils.removeKey("mqtt_msg_" + key);
                    // 不添加到保留集合
                } else {
                    // 保留未过期的键
                    keysToKeep.add(key);
                }
            }
            
            // 计算删除的记录数
            int removedCount = allKeys.size() - keysToKeep.size();
            
            // 更新键集合
            SpUtils.encodeSet("mqtt_msg_keys", keysToKeep);
            
            Timber.tag(TAG).i("清理过期消息记录完成，删除了 " + removedCount + " 条记录");
        } catch (Exception e) {
            Timber.tag(TAG).e("清理过期消息记录失败：" + e.getMessage());
        }
    }


    /**
     * 上报广告播放次数
     */
    public void sendMqttAdPlayCount(HashMap<String, Integer> adPlayCountMap) {
        try {
            // 在MainActivity中已经使用最新的广告播放数据，直接构建上报数据
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            
            // 格式化当前时间
            Calendar calendar = Calendar.getInstance();
            String dateTime = String.format("%04d-%02d-%02d %02d:%02d:00",
                    calendar.get(Calendar.YEAR),
                    calendar.get(Calendar.MONTH) + 1,
                    calendar.get(Calendar.DAY_OF_MONTH),
                    calendar.get(Calendar.HOUR_OF_DAY),
                    calendar.get(Calendar.MINUTE));
            resp.put("datetime", dateTime);
            
            // 添加广告播放次数数组
            JSONArray adListArray = new JSONArray();
            for (Map.Entry<String, Integer> entry : adPlayCountMap.entrySet()) {
                if (entry.getValue() > 0) {  // 只上报有播放次数的广告
                    JSONObject adItem = new JSONObject();
                    adItem.put("id", entry.getKey());
                    adItem.put("count", entry.getValue());
                    adListArray.put(adItem);
                }
            }
            resp.put("adList", adListArray);
            
            // 只在有广告数据时进行上报
            if (adListArray.length() > 0) {
                boolean publishSuccess = MqttUtil.publish(MqttManagerService.TOPIC_AD_PLAY_COUNT, resp.toString(), 1, false);
                
                if (publishSuccess) {
                    // 上报成功，清空计数
                    adPlayCountMap.clear();
                    clearStoredAdPlayCount();
                    Timber.tag(TAG).d("上报广告播放次数成功: %s", resp.toString());
                } else {
                    Timber.tag(TAG).w("上报广告播放次数失败，将在下次上报中重试");
                }
            } else {
                Timber.tag(TAG).d("没有广告播放记录需要上报");
            }
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "上报广告播放次数异常");
        }
    }

    /**
     * 清除本地存储的广告播放次数
     */
    private void clearStoredAdPlayCount() {
        // 清除MainActivity中保存的广告播放计数
        SpUtils.removeKey("ad_play_count");
        Timber.tag(TAG).d("已清除本地存储的广告播放次数");
    }

    /**
     * 库存低于阈值时报警
     */
    public void sendMqttUpdateCompleted() {
        try {
            JSONObject resp = new JSONObject();
            resp.put("mainboardCode", mainboardCode);
            resp.put("uuid", DeviceIdUtil.getUUID());
            resp.put("version", BuildConfig.VERSION_NAME);
            MqttUtil.publish(MqttManagerService.TOPIC_UPDATE_COMPLETED, resp.toString(), 1, false);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}